import {
  ImageryLayer,
  Resource,
  ScreenSpaceEventHandler,
  WebMapTileServiceImageryProvider,
  Proxy
} from "joCesium";
import { Viewer } from "@jodvf/cesium-3d";
import { Mutex } from "async-mutex";
import CesiumViewer from "./CesiumViewer";
/**
 * Cesium Viewer 单例
 */
class CesiumViewerSingleton {
  private static instance: CesiumViewerSingleton;
  private viewer: Viewer | null = null;
  private handler: ScreenSpaceEventHandler | null = null;
  private static mutex = new Mutex();
  // private 禁止new获取
  private constructor() {
    // this.viewer = new Viewer("map", CesiumViewerSingleton.options);
  }
  /**
   * 获取Cesium Viewer 单例
   * @returns CesiumViewerSingleton
   * @description 新增互斥锁，限制只有一个线程访问临界区，避免vue路由跳转后错误访问未销毁完全的单例
   */
  public static getInstance(): CesiumViewerSingleton {
    CesiumViewerSingleton.mutex.acquire();

    try {
      if (!CesiumViewerSingleton.instance) {
        CesiumViewerSingleton.instance = new CesiumViewerSingleton();
      }
    } finally {
      CesiumViewerSingleton.mutex.release();
    }

    return CesiumViewerSingleton.instance;
  }

  /**
   * 获取viewer方法
   * @returns Viewer
   */
  public getViewer(containerId: string): Viewer {
    const el = document.getElementById(containerId);
    if (
      !this.viewer ||
      !this.viewer?.canvas?.height ||
      !el?.childElementCount
    ) {
      if (el) {
        el.innerHTML = "";
      }
      this.viewer = CesiumViewer.initViewer(containerId);
    }
    this.viewer.resize();
    return this.viewer;
  }

  /**
   * 销毁viewer
   */
  public async destroyViewer() {
    if (this.viewer && !this.viewer.isDestroyed()) {
      await this.viewer.destroy();
      this.viewer = null;
    }
  }

  /**
   * 获取Cesium handler
   * @returns ScreenSpaceEventHandler
   */
  public getHandler(containerId: string): ScreenSpaceEventHandler {
    this.getViewer(containerId);
    if (!this.handler) {
      this.handler = new ScreenSpaceEventHandler(
        (this.viewer as Viewer).canvas
      );
    }
    return this.handler;
  }

  /**
   * 配置option
   * @param options Viewer.ConstructorOptions
   */
  public setOptions(options: Viewer["mapOptions"]): void {
    CesiumViewer.options = options;
  }
}

export default CesiumViewerSingleton;
